using System;
using System.Collections.Generic;
using UnityEngine;

public class PlayerControl : MonoBehaviour
{
	[Serializable]
	public class HitAnimationParams
	{
		public HitAnimationsStateEnum hitEnum;

		public int group;

		public bool useHitFromDB = true;

		public HitParamsDB.HitType type;

		public float strength;

		public FloatRange strengthRange = default(FloatRange);

		public float heightAboveNet;

		public FloatRange heightAboveNetRange = default(FloatRange);

		public float spin;

		public FloatRange spinRange = default(FloatRange);

		public bool bounceOff;

		public float maxPower;

		public bool minPowerOn;

		public float minPowerAddition;

		public FloatRange hitSpeedRange = default(FloatRange);

		public float powerStrength = 0.5f;

		public float powerHeight = 0.2f;

		public bool useHeightMinMax;

		public FloatRange heightMin = default(FloatRange);

		public FloatRange heightMax = default(FloatRange);
	}

	public struct ClosestAnimation
	{
		public HitAnimationParams p;

		public float distance;

		public bool found;

		public int index;

		public HitAnimationParams hitParams;
	}

	public class HitPlan
	{
		public HitAnimationInfo hitInfo;

		public KineticPlan.AnimSearchSolution animSearchSolution;

		public float moveAnimSpeed;

		public float hitAnimSpeed;

		public Vector3 startAnimPosition;

		public HitAnimationParams hitParams;

		public float hitFlightTime;

		public KineticPlan.HitPoint hitPoint;

		public int hitIndex;
	}

	public List<Transform> updateBallPos;

	public bool useIK;

	public bool usePowerControl;

	public float startPower = 0.5f;

	public bool updatePowerContiually = true;

	public bool timeIsPower;

	public bool alwaysShowArrow;

	public HitAnimationsStateEnum hitType;

	public FloatRange arrowHeightRange = default(FloatRange);

	public FloatRange mouseSpeedRange = default(FloatRange);

	public FloatRange timeMultRange = default(FloatRange);

	public List<HitAnimationParams> hitAnimations = new List<HitAnimationParams>();

	public List<HitAnimationParams> backHitAnimations = new List<HitAnimationParams>();

	public BallShooter shooter;

	public Transform marker;

	public UISprite markerSprite;

	public Transform marker1;

	public UISprite powerBar;

	public UISprite arrow;

	public UISprite arrow2;

	public QualityLabel qualityLabel;

	private int hitAnimationIndex;

	private List<HitAnimationParams> hitList;

	public bool useClosestAnimationIndex;

	[Range(0.5f, 2f)]
	public float animatorSpeed = 1f;

	[Range(1f, 10f)]
	public float maxMoveSpeed = 3f;

	[Header("Setup")]
	public Camera camera;

	public Vector3 cameraOffset;

	public float cameraDamp = 1f;

	public float cameraSpeed = 3f;

	public PhysicsBall ball;

	private bool ballFlyingTowardsMe;

	public float symDeltaTime = 0.1f;

	public float crossFadeDuration = 0.05f;

	private KineticPlan _kineticPlan;

	private GestureTracker gestureTracker = new GestureTracker();

	private bool isInGesture;

	private Vector3 hitPosition;

	private Vector3 playerPositionWhenHit;

	private Vector3 prevMousePosition;

	private Vector3 lastHitPoint;

	public float maxVelocity = 4f;

	private float timeWhenHit;

	private float perfectHitTime;

	public float minAnimSpeed;

	private int count;

	public float maxMoveDistance;

	public float maxHitAnimatorSpeed = 5f;

	private float desiredPower = 1f;

	public float returnLimit = 0.5f;

	public KineticPlan kineticPlan
	{
		get
		{
			if (_kineticPlan == null)
			{
				_kineticPlan = GetComponent<KineticPlan>();
			}
			return _kineticPlan;
		}
	}

	public void OnShotBall()
	{
		ballFlyingTowardsMe = true;
		arrow.cachedGameObject.SetActive(false);
		if (usePowerControl)
		{
			desiredPower = 0f;
		}
		else
		{
			desiredPower = startPower;
		}
		GoToHit(false);
	}

	private void TryToHit()
	{
		if (kineticPlan.indexOfElementOfType<KineticElementHit>() < 0 && gestureTracker.Count() >= 2)
		{
			HitButtonPressed();
		}
	}

	private List<HitAnimationParams> GetHitList()
	{
		if (Mathf.Sign(gestureTracker.CalculateFirstToLastPoint().z) == Mathf.Sign(base.transform.position.z))
		{
			return backHitAnimations;
		}
		return hitAnimations;
	}

	private void LateUpdate()
	{
		foreach (Transform updateBallPo in updateBallPos)
		{
			Vector3 vector = Camera.main.WorldToScreenPoint(ball.position);
			vector.x /= Screen.width;
			vector.y /= Screen.height;
			Renderer component = updateBallPo.GetComponent<Renderer>();
			Material material = component.material;
			material.SetFloat("_x", vector.x);
			material.SetFloat("_y", vector.y);
		}
	}

	private void Update()
	{
		Vector3 b = hitPosition.OnGround() + Vector3.right * Mathf.Sign(hitPosition.x - playerPositionWhenHit.x) * cameraOffset.x + new Vector3(0f, cameraOffset.y, Mathf.Sign(base.transform.position.z) * cameraOffset.z);
		camera.transform.position = Vector3.Lerp(camera.transform.position, b, Time.deltaTime * cameraSpeed);
		bool mouseButtonDown = Input.GetMouseButtonDown(0);
		bool mouseButtonUp = Input.GetMouseButtonUp(0);
		Vector3 mousePosition = Input.mousePosition;
		if (mouseButtonDown)
		{
			gestureTracker.Clear();
			isInGesture = true;
			prevMousePosition = mousePosition;
		}
		TryToHit();
		if (mouseButtonUp)
		{
			isInGesture = false;
		}
		MoveAnimationInfo moveAnimationInfo = null;
		Vector3 zero = Vector3.zero;
		if (Input.GetKey(KeyCode.A))
		{
			zero.x -= 1f;
		}
		if (Input.GetKey(KeyCode.E))
		{
			zero.x += 1f;
		}
		if (Input.GetKey(KeyCode.O))
		{
			zero.z -= 1f;
		}
		if (Input.GetKey(KeyCode.Comma))
		{
			zero.z += 1f;
		}
		Vector3 zero2 = Vector3.zero;
		if (zero.x != 0f)
		{
			moveAnimationInfo = ((!(zero.x < 0f)) ? ScriptableObjectSingleton<KineticAnimationInfoDB>.instance.GetMoveAnimationByEnum(MoveAnimationsStateEnum.HopRight) : ScriptableObjectSingleton<KineticAnimationInfoDB>.instance.GetMoveAnimationByEnum(MoveAnimationsStateEnum.HopLeft));
			zero2 += Vector3.right * moveAnimationInfo.positionChange.x;
			zero2 += Vector3.forward * moveAnimationInfo.zAdjustRange.LerpMinMax(zero.z * 0.5f);
		}
		else if (zero.z != 0f)
		{
			moveAnimationInfo = ScriptableObjectSingleton<KineticAnimationInfoDB>.instance.GetMoveAnimationByEnum(MoveAnimationsStateEnum.HopLeftShort);
			zero2 += Vector3.forward * moveAnimationInfo.zAdjustRange.LerpMinMax(zero.z * 0.5f);
		}
		KineticPlanElement activeElement = kineticPlan.activeElement;
		KineticElementHit kineticElementHit = activeElement as KineticElementHit;
		if (kineticElementHit != null && kineticPlan.Count == 1 && moveAnimationInfo != null)
		{
			KineticElementMove kineticElementMove = new KineticElementMove();
			kineticElementMove.animatorSpeed = animatorSpeed;
			kineticElementMove.animInfo = moveAnimationInfo;
			kineticElementMove.crossFadeDuration = crossFadeDuration;
			kineticElementMove.useDesiredEnd = true;
			kineticElementMove.startFromCurrentPosition = true;
			kineticElementMove.desiredEndPosition = base.transform.position + base.transform.rotation * zero2;
			kineticPlan.AddElement(kineticElementMove);
		}
		else if ((kineticPlan.activeElement == null || (activeElement.ellapsedTime + activeElement.animatorSpeed * Time.deltaTime >= activeElement.length && kineticPlan.Count == 1)) && kineticPlan.indexOfElementOfType<KineticElementHit>() < 0 && moveAnimationInfo != null)
		{
			kineticPlan.CancelAllPendingElements();
			KineticElementMove kineticElementMove2 = new KineticElementMove();
			kineticElementMove2.animatorSpeed = animatorSpeed;
			kineticElementMove2.animInfo = moveAnimationInfo;
			kineticElementMove2.crossFadeDuration = crossFadeDuration;
			kineticElementMove2.useDesiredEnd = true;
			kineticElementMove2.startFromCurrentPosition = true;
			kineticElementMove2.desiredEndPosition = base.transform.position + base.transform.rotation * zero2;
			kineticPlan.AddElement(kineticElementMove2);
		}
		if (isInGesture)
		{
			gestureTracker.AddScreenPos(mousePosition, camera, Table.tablePlane, ball.flightSequence.flightTime);
		}
		if (ballFlyingTowardsMe)
		{
			if (kineticPlan.indexOfElementOfType<KineticElementHit>() < 0 && updatePowerContiually && !usePowerControl)
			{
				UpdatePower(ball.flightSequence.flightTime - ball.flightSequence.GetStageThatStartsFromTableSide(base.transform.position.z).startTime);
			}
			if (usePowerControl)
			{
				if (timeIsPower)
				{
					if (kineticPlan.indexOfElementOfType<KineticElementHit>() >= 0)
					{
						desiredPower += timeMultRange.min * Time.deltaTime;
					}
				}
				else if (isInGesture && gestureTracker.Count() > 1)
				{
					float num = Vector3.Distance(prevMousePosition, mousePosition) / (float)Screen.height;
					num = gestureTracker.FirstToLastScreen().magnitude / (gestureTracker.FirstToLastTime() * (float)Screen.height);
					desiredPower += timeMultRange.Lerp(mouseSpeedRange.InverseLerp(num)) * Time.deltaTime;
					desiredPower = mouseSpeedRange.InverseLerp(gestureTracker.FirstToLastScreen().magnitude);
				}
				powerBar.fillAmount = desiredPower;
			}
		}
		powerBar.fillAmount = Mathf.Lerp(powerBar.fillAmount, desiredPower, Time.deltaTime * 60f);
		arrow.height = (int)arrowHeightRange.Lerp(powerBar.fillAmount);
		arrow2.fillAmount = Mathf.InverseLerp(0f, arrowHeightRange.max, arrow.height);
		if (gestureTracker.Count() > 1)
		{
			Vector3 vector = gestureTracker.CalculateFirstToLastPoint().OnGround();
			Quaternion quaternion = Quaternion.LookRotation(vector.OnGround());
			arrow.cachedTransform.localRotation = Quaternion.Euler(Vector3.back * quaternion.eulerAngles.y);
		}
		markerSprite.fillAmount = powerBar.fillAmount;
		prevMousePosition = mousePosition;
		float flightTime = ball.flightSequence.flightTime;
		float num2 = flightTime - Time.deltaTime;
		if (num2 <= perfectHitTime && flightTime >= perfectHitTime && ballFlyingTowardsMe)
		{
			arrow.GetComponent<Arrow>().AnimateSelection();
		}
	}

	private void HitButtonPressed()
	{
		GoToHit(true);
	}

	private KineticPlan.HitPoint HitPoint(HitAnimationInfo hitInfo)
	{
		return KineticPlan.FindHitPoint(ball, base.transform.position.z, symDeltaTime, hitInfo, base.transform, maxVelocity);
	}

	private ClosestAnimation GetClosestAnimationIndex(List<HitAnimationParams> hitList)
	{
		ClosestAnimation result = default(ClosestAnimation);
		int num = -1;
		foreach (HitAnimationParams hit in hitList)
		{
			num++;
			HitAnimationsStateEnum hitEnum = hit.hitEnum;
			HitAnimationInfo orCreateHitAnimationByEnum = ScriptableObjectSingleton<KineticAnimationInfoDB>.instance.GetOrCreateHitAnimationByEnum(hitEnum);
			KineticPlan.HitPoint hitPoint = HitPoint(orCreateHitAnimationByEnum);
			if (hitPoint.foundHitPosition)
			{
				float num2 = Vector3.Distance(hitPoint.hitAnimationStartPosition, base.transform.position);
				num2 = Mathf.Abs(hitPoint.hitAnimationStartPosition.x - base.transform.position.x);
				if (!result.found || result.distance > num2)
				{
					result.found = true;
					result.distance = num2;
					result.p = hit;
					result.index = num;
				}
			}
		}
		return result;
	}

	private void GoToHit(bool shouldHit)
	{
		GoToHit2(shouldHit);
	}

	private void GoToHit2(bool shouldHit, bool comeClose = false)
	{
		if (shouldHit && kineticPlan.indexOfElementOfType<KineticElementHit>() >= 0)
		{
			return;
		}
		kineticPlan.CancelAllPendingElements();
		bool flag = true;
		hitList = GetHitList();
		Time.timeScale = shooter.timeScale;
		List<HitPlan> list = new List<HitPlan>();
		KineticPlan.HitPoint hitPoint = default(KineticPlan.HitPoint);
		KineticPlan.TransformState transformStateAfterAllAnimationsFinish = kineticPlan.GetTransformStateAfterAllAnimationsFinish();
		int num = -1;
		foreach (HitAnimationParams hit in hitList)
		{
			num++;
			HitAnimationInfo orCreateHitAnimationByEnum = ScriptableObjectSingleton<KineticAnimationInfoDB>.instance.GetOrCreateHitAnimationByEnum(hit.hitEnum);
			hitPoint = (comeClose ? KineticPlan.FindHitPoint(ball, base.transform.position.z, symDeltaTime, orCreateHitAnimationByEnum, base.transform, maxVelocity) : KineticPlan.FindHitPointClosestToPlayer(ball, base.transform.position.z, symDeltaTime, orCreateHitAnimationByEnum, base.transform));
			if (hitPoint.foundHitPosition)
			{
				Vector3 vector = (hitPoint.maxPosition - transformStateAfterAllAnimationsFinish.rotation * orCreateHitAnimationByEnum.hitPosition).OnGround();
				KineticPlan.SearchParams p = KineticPlan.SearchParams.FromStartToEndPos(transformStateAfterAllAnimationsFinish.position, vector, transformStateAfterAllAnimationsFinish.rotation, orCreateHitAnimationByEnum);
				p.maxDepth = 1;
				KineticPlan.AnimSearchSolution animSearchSolution = kineticPlan.FindPathToGetToPosition(p);
				float hitTime = orCreateHitAnimationByEnum.hitTime;
				float totalDuration = animSearchSolution.totalDuration;
				float num2 = hitPoint.maxTime + hitPoint.stage.startTime - ball.flightSequence.flightTime;
				float duration = transformStateAfterAllAnimationsFinish.duration;
				float num3 = num2 - duration;
				float num4 = 1f;
				float num5 = 1f;
				if (!(num3 <= 0f))
				{
					float num6 = num3 - hitTime;
					float num7 = animSearchSolution.desiredPositionChange.magnitude / num3;
					num4 = maxMoveSpeed / num7;
					float num8 = num2 - (duration + totalDuration / num4);
					num5 = orCreateHitAnimationByEnum.hitTime / num8;
					HitPlan hitPlan = new HitPlan();
					hitPlan.hitInfo = orCreateHitAnimationByEnum;
					hitPlan.animSearchSolution = animSearchSolution;
					hitPlan.moveAnimSpeed = num4;
					hitPlan.hitAnimSpeed = num5;
					hitPlan.startAnimPosition = vector;
					hitPlan.hitParams = hit;
					hitPlan.hitFlightTime = hitPoint.maxTime + hitPoint.stage.startTime;
					hitPlan.hitPoint = hitPoint;
					hitPlan.hitIndex = num;
					list.Add(hitPlan);
				}
			}
		}
		HitPlan hitPlan2 = null;
		foreach (HitPlan item in list)
		{
			if (!(item.hitAnimSpeed > item.hitParams.hitSpeedRange.max) && !(item.hitAnimSpeed <= 0f))
			{
				if (hitPlan2 == null)
				{
					hitPlan2 = item;
				}
				else if (item.hitParams.group < hitPlan2.hitParams.group || (item.hitParams.group == hitPlan2.hitParams.group && Mathf.Abs(item.animSearchSolution.desiredPositionChange.x) < Mathf.Abs(hitPlan2.animSearchSolution.desiredPositionChange.x)))
				{
					hitPlan2 = item;
				}
			}
		}
		if (hitPlan2 == null)
		{
			isInGesture = false;
			gestureTracker.Clear();
			if (kineticPlan.indexOfElementOfType<KineticElementHit>() != 0)
			{
				float num9 = Mathf.Sign(base.transform.position.z) * gestureTracker.CalculateFirstToLastPoint().x;
				HitAnimationsStateEnum hitEnum = hitList[Mathf.Clamp((num9 < 0f) ? 1 : 0, 0, hitList.Count - 1)].hitEnum;
				hitAnimationIndex = 0;
				kineticPlan.CancelAllPendingElements();
				HitAnimationInfo orCreateHitAnimationByEnum2 = ScriptableObjectSingleton<KineticAnimationInfoDB>.instance.GetOrCreateHitAnimationByEnum(hitEnum);
				KineticElementHit kineticElementHit = new KineticElementHit();
				kineticElementHit.animInfo = orCreateHitAnimationByEnum2;
				kineticElementHit.animatorSpeed = 2f;
				kineticElementHit.crossFadeDuration = crossFadeDuration;
				kineticElementHit.trackFlight = null;
				kineticElementHit.startFromCurrentPosition = true;
				kineticPlan.AddElement(kineticElementHit);
			}
			return;
		}
		bool flag2 = false;
		KineticPlan.AnimSearchSolution animSearchSolution2 = hitPlan2.animSearchSolution;
		Vector3 startPosition = hitPlan2.animSearchSolution.startPosition;
		Quaternion startRotation = hitPlan2.animSearchSolution.startRotation;
		for (int i = 0; i < animSearchSolution2.animList.Count; i++)
		{
			MoveAnimationInfo moveAnimationInfo = animSearchSolution2.animList[i];
			KineticElementMove kineticElementMove = new KineticElementMove();
			kineticElementMove.animInfo = moveAnimationInfo;
			if (flag2)
			{
				kineticElementMove.startPosition = animSearchSolution2.startPosition;
				kineticElementMove.startRotation = animSearchSolution2.startRotation;
				flag2 = false;
			}
			else
			{
				kineticElementMove.startFromCurrentPosition = true;
			}
			kineticElementMove.animatorSpeed = hitPlan2.moveAnimSpeed;
			kineticElementMove.crossFadeDuration = crossFadeDuration;
			startPosition += startRotation * (moveAnimationInfo.positionChange + moveAnimationInfo.GetAdjustVector(animSearchSolution2.xAdjust, animSearchSolution2.zAdjust));
			startRotation *= moveAnimationInfo.rotationChange;
			kineticElementMove.useDesiredEnd = true;
			kineticElementMove.desiredEndPosition = startPosition;
			kineticPlan.AddElement(kineticElementMove);
		}
		bool flag3 = true;
		if (shouldHit)
		{
			Debug.Log("Hit Anim speed " + hitPlan2.hitAnimSpeed + " move speed " + hitPlan2.moveAnimSpeed);
			hitAnimationIndex = hitPlan2.hitIndex;
			KineticElementHit kineticElementHit2 = new KineticElementHit();
			HitAnimationInfo hitAnimationInfo = (HitAnimationInfo)(kineticElementHit2.animInfo = hitPlan2.hitInfo);
			if (flag3)
			{
				kineticElementHit2.useIK = useIK;
				kineticElementHit2.useDesiredEnd = true;
				kineticElementHit2.desiredEndPosition = hitPlan2.startAnimPosition + startRotation * hitAnimationInfo.positionChange;
				kineticElementHit2.trackFlight = ball.flightSequence;
				kineticElementHit2.animatorSpeed = hitPlan2.hitAnimSpeed;
				kineticElementHit2.animatorSpeedAfterHit = Mathf.Clamp(1f / kineticElementHit2.animatorSpeed, 0.75f, 2f);
				kineticElementHit2.normalizedReactionTime = Mathf.InverseLerp(hitPlan2.hitFlightTime - hitPlan2.animSearchSolution.totalDuration * hitPlan2.moveAnimSpeed - hitAnimationInfo.hitTime / maxHitAnimatorSpeed, hitPlan2.hitFlightTime - hitAnimationInfo.hitTime / maxHitAnimatorSpeed, ball.flightSequence.flightTime);
			}
			kineticElementHit2.startFromCurrentPosition = true;
			kineticElementHit2.crossFadeDuration = crossFadeDuration;
			kineticElementHit2.hitPosition = hitPlan2.hitPoint.maxPosition + hitAnimationInfo.racketRotationAtHit * (Vector3.back * ball.transform.localScale.z * 0.5f);
			kineticElementHit2.flightTimeWhenHit = hitPlan2.hitFlightTime;
			kineticElementHit2.onHitDelegate = OnHitDelegate;
			kineticPlan.AddElement(kineticElementHit2);
			Vector3 vector2 = ball.flightSequence.Position();
			vector2.y = marker.position.y;
			marker1.transform.position = kineticElementHit2.hitPosition;
			arrow.cachedGameObject.SetActive(true);
			arrow.cachedTransform.position = kineticElementHit2.hitPosition;
			arrow.cachedTransform.position = marker.position;
			timeWhenHit = ball.flightSequence.flightTime;
			UpdatePower(GetTiming());
			float timing = GetTiming();
			HitParamsDB.TimingRange timingRange = ScriptableObjectSingleton<HitParamsDB>.instance.timing.GetTimingRange(timing, 0f, 200f);
			qualityLabel.SetQuality(timingRange.message, timingRange.color, hitPosition);
			arrow.GetComponent<Arrow>().SetColor(timingRange.color);
		}
		else
		{
			perfectHitTime = ball.flightSequence.GetStageThatStartsFromTableSide(base.transform.position.z).startTime;
			marker.transform.position = ball.flightSequence.PositionAt(perfectHitTime);
			marker.transform.localScale = new Vector3(0.2f, 0.02f, 0.2f);
			arrow.GetComponent<Arrow>().SetColor(Color.white);
			HitAnimationInfo hitInfo = hitPlan2.hitInfo;
			playerPositionWhenHit = hitPlan2.startAnimPosition + startRotation * hitInfo.positionChange;
			hitPosition = hitPlan2.hitPoint.maxPosition;
			arrow.cachedTransform.position = hitPosition;
			if (alwaysShowArrow)
			{
				arrow.cachedGameObject.SetActive(true);
			}
		}
	}

	private void OnHitDelegate(KineticElementHit hit)
	{
		HitBall(hit);
		gestureTracker.Clear();
	}

	private Vector3 GetPositionToAimFor(Vector3 ballPos)
	{
		float num = 0f - Mathf.Sign(base.transform.position.z);
		Vector3 vector = gestureTracker.CalculateFirstToLastPoint();
		if (vector == Vector3.zero)
		{
			return new Vector3(0f, 0f, 0.5f * num * Table.halfLength);
		}
		if (Mathf.Sign(vector.z) != num)
		{
			vector.z *= -1f;
			vector.x *= -1f;
		}
		float num2 = Mathf.Abs(num * Table.halfLength - ballPos.z);
		float num3 = vector.x / vector.z * num2;
		Vector3 vector2 = ballPos;
		float num4 = Mathf.Clamp(vector2.x, 0f - Table.halfwidth, Table.halfwidth) + num3;
		return new Vector3(num4 * 0.75f, 0f, num * Table.halfLength);
	}

	private float GetNormSpeed()
	{
		return Mathf.Sign(timeWhenHit - perfectHitTime) * (1f - Mathf.InverseLerp(0.05f, 0.2f, Mathf.Abs(perfectHitTime - timeWhenHit)));
	}

	private float GetTiming()
	{
		return timeWhenHit - perfectHitTime;
	}

	private void HitBall(KineticElementHit hit)
	{
		arrow.cachedGameObject.SetActive(false);
		Time.timeScale = shooter.timeScale;
		ballFlyingTowardsMe = false;
		float f = Mathf.Max(0f, hit.flightTimeWhenHit - ball.flightSequence.flightTime);
		Vector3 vector = ball.flightSequence.PositionAt(hit.flightTimeWhenHit);
		float num = 0f - Mathf.Sign(base.transform.position.z);
		Vector3 vector2 = vector;
		Vector3 normalized = (GetPositionToAimFor(vector) - vector2).OnGround().normalized;
		HitAnimationParams hitAnimationParams = hitList[hitAnimationIndex % hitList.Count];
		float num2 = hitAnimationParams.hitSpeedRange.InverseLerp(hit.desiredAnimatorSpeed);
		num2 = 1f - hit.normalizedReactionTime;
		float num3 = Mathf.Clamp01(Mathf.Abs(gestureTracker.FirstToLastSpeed()) / 6000f);
		num2 = num3;
		num2 = 1f;
		float num4 = hit.flightTimeWhenHit - hit.hitInfo.hitTime / 1.5f - timeWhenHit;
		num4 = hit.flightTimeWhenHit - 0.2f - timeWhenHit;
		num4 = perfectHitTime - timeWhenHit;
		num2 = 1f - Mathf.InverseLerp(0f, 0.3f, Mathf.Max(1f - hit.desiredAnimatorSpeed, 0f));
		num2 = Mathf.Abs(GetNormSpeed());
		bool flag = num3 > 0.5f;
		float aimHeightAboveNet = hitAnimationParams.heightAboveNetRange.Lerp(num2);
		if (hitAnimationParams.useHeightMinMax)
		{
			aimHeightAboveNet = ((!(GetNormSpeed() < 0f)) ? hitAnimationParams.heightMax.Lerp(num2) : hitAnimationParams.heightMin.Lerp(num2));
		}
		float angularVelocityMagnitude = hitAnimationParams.spinRange.Lerp(num2);
		float num5 = hitAnimationParams.strengthRange.Lerp(num2);
		if (hitAnimationParams.useHitFromDB)
		{
			HitParamsDB.Hit hit2 = ScriptableObjectSingleton<HitParamsDB>.instance.GetHit(hitAnimationParams.type);
			float timing = hit2.timingInSecs.LerpMinMax((0.5f - desiredPower) * 2f);
			if (!usePowerControl)
			{
				timing = GetTiming();
			}
			HitParamsDB.TimingRange timingRange = ScriptableObjectSingleton<HitParamsDB>.instance.timing.GetTimingRange(GetTiming(), 0f, 200f);
			float normTiming = ScriptableObjectSingleton<HitParamsDB>.instance.timing.GetNormTiming(GetTiming(), 200f);
			float quality = timingRange.GetQuality(normTiming, 0f);
			HitParamsDB.HitParams hitParams = ScriptableObjectSingleton<HitParamsDB>.instance.GetHit(hitAnimationParams.type).GetHitParams(timing, quality, ball.flightSequence.GetStageThatStartsFromTableSide(base.transform.position.z), 0);
			num5 = hitParams.strength;
			aimHeightAboveNet = hitParams.heightAboveNet;
			angularVelocityMagnitude = hitParams.spin;
		}
		FlightInitialConditionsSearch instance = FlightInitialConditionsSearch.instance;
		if (hitAnimationParams.bounceOff)
		{
			instance.velocityMagnitudeBoundaries.max = Mathf.Abs(ball.flightSequence.Velocity().magnitude) + hitAnimationParams.maxPower;
		}
		else
		{
			instance.velocityMagnitudeBoundaries.max = 5f;
		}
		if (hitAnimationParams.minPowerOn)
		{
			instance.velocityMagnitudeBoundaries.min = Mathf.Abs(ball.flightSequence.Velocity().magnitude) + hitAnimationParams.minPowerAddition;
		}
		else
		{
			instance.velocityMagnitudeBoundaries.min = 0f;
		}
		instance.velocityMagnitudeBoundaries.max = 25f;
		instance.velocityMagnitudeBoundaries.min = 0f;
		instance.Setup(normalized, vector2);
		float angle = FlightInitialConditionsSearch.GetAngle(aimHeightAboveNet, 0.02f, vector2);
		FlightInitialConditionsSearch.MaxResult maxResult = instance.FindMaxAcceptableVelocity(angle, angularVelocityMagnitude, FlightInitialConditionsSearch.OptimumSearchType.SearchMin);
		FlightInitialConditionsSearch.MaxResult maxResult2 = instance.FindMaxAcceptableVelocity(angle, angularVelocityMagnitude, FlightInitialConditionsSearch.OptimumSearchType.SearchMax);
		float num6 = Mathf.Lerp(maxResult.magnitude, maxResult2.magnitude, num5);
		num6 = maxResult.magnitude + (maxResult2.magnitude - maxResult.magnitude) * num5;
		FlightParams initialConditions = instance.GetInitialConditions(num6, angle, angularVelocityMagnitude);
		FlightSimulator instance2 = Singleton<FlightSimulator>.instance;
		FlightSimulator.SequenceSimulationParams sim = FlightSimulator.SequenceSimulationParams.DefaultRecordFlightParams(initialConditions, instance.symFlight);
		instance2.FillFlightSequence(ball.flightSequence, sim);
		ball.flightSequence.Reset();
		ball.flightSequence.Update(Mathf.Abs(f));
		if (shooter != null)
		{
			shooter.OnBallReturned();
		}
		isInGesture = false;
		gestureTracker.Clear();
	}

	private void UpdatePower(float timing)
	{
		HitParamsDB.Hit hit = ScriptableObjectSingleton<HitParamsDB>.instance.GetHit(HitParamsDB.HitType.TopspinHit);
		float normTiming = hit.GetNormTiming(timing, ball.flightSequence.GetStageThatStartsFromTableSide(base.transform.position.z));
		if (!usePowerControl)
		{
			desiredPower = 1f - (1f + normTiming) * 0.5f;
		}
		Color a = ((!(desiredPower >= 0.5f)) ? Color.green : Color.yellow);
		Color b = ((!(desiredPower >= 0.5f)) ? Color.yellow : Color.red);
		Color color = Color.Lerp(a, b, 2f * Mathf.Repeat(desiredPower, 0.5f));
	}
}
